/**************************************************************************(C)*
 *
 *  This file is part of the GreenHills project
 *  Copyright (C) 2009  Tieto Corporation
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  Not for commmercial use. Only with Tieto permission.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************(C)*/

#pragma once

#include <vector>

#include "eventdll.h"

namespace greenhills {

namespace util {
    class obinstream;
    class ibinstream;
}

namespace event {

/**
  * @brief Base event object class
  *
  * Event object for communication between client and server.
  * It has an ability to serialize itself to obinstream and deserialize
  * from ibinstream.
  */
class GH_EVENT_CLASS CEvent
{
public:
    enum eEventType
    {
        LoginRequest = 0,
        LoginResponse,
        LogoutRequest,
        LogoutResponse,
        CreateRoomRequest,
        CreateRoomResponse,
        JoinRoomRequest,
        JoinRoomResponse,
        LeaveRoomRequest,
        LeaveRoomResponse,
        AddObjectRequest,
        AddObjectResponse,
        UpdateObjectRequest,
        UpdateObjectResponse,
        RemoveObjectRequest,
        RemoveObjectResponse,

        ObjectAddedEvent = 100,
        ObjectUpdatedEvent,
        ObjectRemovedEvent,
        IdentificationEvent,
    };

public:
    CEvent();
    virtual ~CEvent();

public:
    virtual eEventType type() const = 0;
    virtual util::obinstream& operator<<(util::obinstream &pStream) const;
    virtual util::ibinstream& operator>>(util::ibinstream &pStream);

public:
    static void serialize(const CEvent *event, util::obinstream &pStream);
    static CEvent *deserialize(util::ibinstream &pStream);
};

/**
  * @brief Event builder base interface
  *
  * Descendants of this class creates CEvent object of some specific type.
  * Implementions of these descendants are provided by REGISTER_EVENT macro.
  */
class IEventBuilder
{
public:
    virtual CEvent* build() const = 0;
    virtual CEvent::eEventType type() const = 0;
};

/**
  * @brief Event factory object
  *
  * Creates CEvent object of desired type. Holds list about all event types
  * (held as a list of IEventBuilder descendants).
  */
class CEventFactory
{
public:
    void registerBuilder(IEventBuilder* builder);
    CEvent* buildEvent(CEvent::eEventType type);

    std::vector<IEventBuilder*> builders;

    static CEventFactory& instance()
    {
        static CEventFactory *inst = new CEventFactory();
        return *inst;
    }

private:
    CEventFactory();
};

#define REGISTER_EVENT( id, base ) \
class base##Builder : public IEventBuilder \
{\
public:\
    base##Builder() : IEventBuilder()\
    {\
        CEventFactory::instance().registerBuilder(this);\
    }\
public:\
    virtual CEvent::eEventType type() const\
    {\
        return id;\
    }\
    \
    virtual CEvent* build() const\
    {\
        return new base();\
    }\
};\
base##Builder base##BuilderInstance;

} //namespace event
} //namespace greenhills
